package com.ruoyi.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.constant.PublishConstants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.bo.AttrBo;
import com.ruoyi.system.domain.bo.PStoreProductBo;
import com.ruoyi.system.domain.vo.PStoreProductCouponVo;
import com.ruoyi.system.domain.vo.PStoreProductVo;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.IPStoreProductService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 商品Service业务层处理
 *
 * @author ruoyi
 * @date 2022-08-01
 */
@RequiredArgsConstructor
@Service
public class PStoreProductServiceImpl implements IPStoreProductService {

    private final PStoreProductMapper baseMapper;
    private final PStoreProductAttrValueMapper attrValueMapper;
    private final PStoreProductCouponMapper couponMapper;
    private final PAttrCommonMapper commonMapper;
    private final PAskCouponMapper askCouponMapper;
    private final PStoreSeckillMapper pStoreSeckillMapper;

    /**
     * 查询商品
     */
    @Override
    public PStoreProductVo queryById(Long id){
        PStoreProductVo pStoreProductVo = baseMapper.selectFontVoById(id);
        if (ObjectUtil.isEmpty(pStoreProductVo)) {
            throw new ServiceException("非法商品！");
        }
        // 完善购物券
        List<PStoreProductCouponVo> couponVos = couponMapper.selectVoList(new LambdaQueryWrapper<PStoreProductCoupon>().eq(PStoreProductCoupon::getProductId, id));
        if (CollectionUtil.isNotEmpty(couponVos)) {
            pStoreProductVo.setCouponIds(couponVos.stream().map(PStoreProductCouponVo::getIssueCouponId).collect(Collectors.toList()));
            List<PAskCoupon> pAskCoupons = askCouponMapper.selectList(new LambdaQueryWrapper<PAskCoupon>().in(PAskCoupon::getId, pStoreProductVo.getCouponIds()));
            pStoreProductVo.setCoupons(pAskCoupons);
        }
        // 完善商品规格
        List<PStoreProductAttrValue> attrValueVoList = attrValueMapper.selectLeftOssList(new LambdaQueryWrapper<PStoreProductAttrValue>()
            .eq(PStoreProductAttrValue::getProductId, id)
            .eq(PStoreProductAttrValue::getType, "0")
            .eq(PStoreProductAttrValue::getDelFlag, "0"));
        pStoreProductVo.setAttrValue(attrValueVoList);
        // 设置规格回显数据结构
        List<PAttrCommon> attrCommons = commonMapper.selectList(new LambdaQueryWrapper<PAttrCommon>()
            .eq(PAttrCommon::getProductId, id)
            .eq(PAttrCommon::getType, PublishConstants.COMMON_NO));
        List<AttrBo> res = new ArrayList<>();
        attrCommons.forEach(e -> {
            AttrBo attrBo = new AttrBo();
            List<String> v = (List<String>)JSONUtil.parse(e.getStrValue());
            attrBo.setItem(v);
            attrBo.setName(e.getStrKey());
            res.add(attrBo);
        });
        pStoreProductVo.setAttr(res);

        return pStoreProductVo;
    }

    /**
     * 查询商品列表
     */
    @Override
    public TableDataInfo<PStoreProductVo> queryPageList(PStoreProductBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<PStoreProduct> lqw = buildQueryWrapper(bo);
        Page<PStoreProductVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询商品列表
     */
    @Override
    public List<PStoreProductVo> queryList(PStoreProductBo bo) {
        LambdaQueryWrapper<PStoreProduct> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<PStoreProduct> buildQueryWrapper(PStoreProductBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<PStoreProduct> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getMerId() != null, PStoreProduct::getMerId, bo.getMerId());
        lqw.eq(StringUtils.isNotBlank(bo.getImage()), PStoreProduct::getImage, bo.getImage());
        lqw.eq(StringUtils.isNotBlank(bo.getSliderImage()), PStoreProduct::getSliderImage, bo.getSliderImage());
        lqw.like(StringUtils.isNotBlank(bo.getStoreName()), PStoreProduct::getStoreName, bo.getStoreName());
        lqw.eq(StringUtils.isNotBlank(bo.getStoreInfo()), PStoreProduct::getStoreInfo, bo.getStoreInfo());
        lqw.eq(StringUtils.isNotBlank(bo.getKeyword()), PStoreProduct::getKeyword, bo.getKeyword());
        lqw.eq(StringUtils.isNotBlank(bo.getBarCode()), PStoreProduct::getBarCode, bo.getBarCode());
        lqw.eq(StringUtils.isNotBlank(bo.getCateId()), PStoreProduct::getCateId, bo.getCateId());
        lqw.eq(bo.getPrice() != null, PStoreProduct::getPrice, bo.getPrice());
        lqw.eq(bo.getVipPrice() != null, PStoreProduct::getVipPrice, bo.getVipPrice());
        lqw.eq(bo.getOtPrice() != null, PStoreProduct::getOtPrice, bo.getOtPrice());
        lqw.eq(bo.getPostage() != null, PStoreProduct::getPostage, bo.getPostage());
        lqw.like(StringUtils.isNotBlank(bo.getUnitName()), PStoreProduct::getUnitName, bo.getUnitName());
        lqw.eq(bo.getSort() != null, PStoreProduct::getSort, bo.getSort());
        lqw.eq(bo.getSales() != null, PStoreProduct::getSales, bo.getSales());
        lqw.eq(bo.getStock() != null, PStoreProduct::getStock, bo.getStock());
        lqw.eq(bo.getIsShow() != null, PStoreProduct::getIsShow, bo.getIsShow());
        lqw.eq(bo.getIsHot() != null, PStoreProduct::getIsHot, bo.getIsHot());
        lqw.eq(bo.getIsBenefit() != null, PStoreProduct::getIsBenefit, bo.getIsBenefit());
        lqw.eq(bo.getIsBest() != null, PStoreProduct::getIsBest, bo.getIsBest());
        lqw.eq(bo.getIsNew() != null, PStoreProduct::getIsNew, bo.getIsNew());
        lqw.eq(bo.getAddTime() != null, PStoreProduct::getAddTime, bo.getAddTime());
        lqw.eq(bo.getIsPostage() != null, PStoreProduct::getIsPostage, bo.getIsPostage());
        lqw.eq(bo.getMerUse() != null, PStoreProduct::getMerUse, bo.getMerUse());
        lqw.eq(bo.getGiveIntegral() != null, PStoreProduct::getGiveIntegral, bo.getGiveIntegral());
        lqw.eq(bo.getCost() != null, PStoreProduct::getCost, bo.getCost());
        lqw.eq(bo.getIsSeckill() != null, PStoreProduct::getIsSeckill, bo.getIsSeckill());
        lqw.eq(bo.getIsBargain() != null, PStoreProduct::getIsBargain, bo.getIsBargain());
        lqw.eq(bo.getIsGood() != null, PStoreProduct::getIsGood, bo.getIsGood());
        lqw.eq(bo.getIsSub() != null, PStoreProduct::getIsSub, bo.getIsSub());
        lqw.eq(bo.getFicti() != null, PStoreProduct::getFicti, bo.getFicti());
        lqw.eq(bo.getBrowse() != null, PStoreProduct::getBrowse, bo.getBrowse());
        lqw.eq(StringUtils.isNotBlank(bo.getCodePath()), PStoreProduct::getCodePath, bo.getCodePath());
        lqw.eq(StringUtils.isNotBlank(bo.getSoureLink()), PStoreProduct::getSoureLink, bo.getSoureLink());
        lqw.eq(StringUtils.isNotBlank(bo.getVideoLink()), PStoreProduct::getVideoLink, bo.getVideoLink());
        lqw.eq(bo.getTempId() != null, PStoreProduct::getTempId, bo.getTempId());
        lqw.eq(bo.getSpecType() != null, PStoreProduct::getSpecType, bo.getSpecType());
        lqw.eq(StringUtils.isNotBlank(bo.getActivity()), PStoreProduct::getActivity, bo.getActivity());
        lqw.eq(StringUtils.isNotBlank(bo.getFlatPattern()), PStoreProduct::getFlatPattern, bo.getFlatPattern());
        lqw.eq(bo.getIsRecycle() != null, PStoreProduct::getIsRecycle, bo.getIsRecycle());
        return lqw;
    }

    /**
     * 新增商品
     */
    @Override
    public Boolean insertByBo(PStoreProductBo bo) {
        PStoreProduct add = BeanUtil.toBean(bo, PStoreProduct.class);
        add.setIsShow("1");
        // 设置规格属性
        List<AttrBo> attr = bo.getAttr();
        if (CollectionUtil.isEmpty(attr)) {
            throw new ServiceException("规格属性不能为空！");
        }
        List<PStoreProductAttrValue> attrValues = bo.getAttrValue();
        // 设置金额属性
        if (CollectionUtil.isEmpty(attrValues)) {
            throw new ServiceException("规格属性不能为空！");
        }

        PStoreProductAttrValue storeProductAttrValue = attrValues.stream().min(Comparator.comparing(PStoreProductAttrValue::getPrice)).get();
        add.setPrice(storeProductAttrValue.getPrice());
        add.setOtPrice(storeProductAttrValue.getOtPrice());
        add.setCost(storeProductAttrValue.getCost());
        add.setStock(attrValues.stream().filter(e -> e.getStock() != null).mapToInt(PStoreProductAttrValue::getStock).sum());
        baseMapper.insert(add);
        // 普通商品存储规格
        List<PAttrCommon> commonBos = new ArrayList<>();
        for (AttrBo attrBo : attr) {
            PAttrCommon commonBo = new PAttrCommon();
            String v = JSONUtil.toJsonStr(attrBo.getItem());
            commonBo.setStrKey(attrBo.getName());
            commonBo.setStrValue(v);
            commonBo.setProductId(add.getId());
            commonBo.setType("0");
            commonBos.add(commonBo);
        }
        commonMapper.insertBatch(commonBos);
        // 填充规格属性
        String attrStr = attr.stream().map(AttrBo::getName).collect(Collectors.joining(","));
        attrValues.forEach(e -> {
            e.setAttrValue(attrStr);
            e.setProductId(add.getId());
        });
        attrValueMapper.insertBatch(attrValues);
        // 设置购物券
        List<Long> couponIds = bo.getCouponIds();
        if (CollectionUtil.isNotEmpty(couponIds)) {
            List<PStoreProductCoupon> couponBos = new ArrayList<>();
            couponIds.forEach(e -> {
                PStoreProductCoupon productCouponBo = new PStoreProductCoupon();
                productCouponBo.setProductId(add.getId());
                productCouponBo.setIssueCouponId(e);
                couponBos.add(productCouponBo);
            });

            couponMapper.insertBatch(couponBos);
        }

        return true;
    }

    /**
     * 修改商品
     */
    @Override
    public Boolean updateByBo(PStoreProductBo bo) {
        PStoreProduct update = BeanUtil.toBean(bo, PStoreProduct.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(PStoreProduct entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除商品
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public TableDataInfo<PStoreProduct> queryPageMyList(PStoreProduct bo, PageQuery pageQuery) {
        QueryWrapper<PStoreProduct> lqw = Wrappers.query();
        lqw.eq("p.del_flag", UserConstants.NORMAL);
        lqw.eq(bo.getMerId() != null, "p.mer_id", bo.getMerId());
        lqw.like(StringUtils.isNotBlank(bo.getStoreName()), "p.store_name", bo.getStoreName());
        lqw.eq(bo.getCateId() != null, "p.cate_id", bo.getCateId());
        if (StringUtils.isNotBlank(bo.getKeyword())) {
            lqw.and(i -> i.or().eq("p.id", bo.getKeyword())
                .or().like("p.store_name", bo.getKeyword()));
        }

        Page<PStoreProduct> result = baseMapper.selectVoMyPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    @Override
    public boolean updateByMyBo(PStoreProductBo bo) {
        PStoreProduct add = BeanUtil.toBean(bo, PStoreProduct.class);
        long productId = add.getId();
        // 设置规格属性
        List<AttrBo> attr = bo.getAttr();
        if (CollectionUtil.isEmpty(attr)) {
            throw new ServiceException("规格属性不能为空！");
        }
        List<PStoreProductAttrValue> attrValues = bo.getAttrValue();
        // 设置金额属性
        if (CollectionUtil.isEmpty(attrValues)) {
            throw new ServiceException("规格属性不能为空！");
        }

        PStoreProductAttrValue storeProductAttrValue = attrValues.stream().min(Comparator.comparing(PStoreProductAttrValue::getPrice)).get();
        add.setPrice(storeProductAttrValue.getPrice());
        add.setOtPrice(storeProductAttrValue.getOtPrice());
        add.setCost(storeProductAttrValue.getCost());
        add.setStock(attrValues.stream().filter(e -> e.getStock() != null).mapToInt(PStoreProductAttrValue::getStock).sum());
        baseMapper.updateById(add);
        // 删除旧的存储规格
        commonMapper.deleteByProductId(productId);
        // 重新设置存储规格
        List<PAttrCommon> commonBos = new ArrayList<>();
        for (AttrBo attrBo : attr) {
            PAttrCommon commonBo = new PAttrCommon();
            String v = JSONUtil.toJsonStr(attrBo.getItem());
            commonBo.setStrKey(attrBo.getName());
            commonBo.setStrValue(v);
            commonBo.setProductId(productId);
            commonBos.add(commonBo);
        }
        commonMapper.insertBatch(commonBos);
        // 删除旧的规格属性
        attrValueMapper.delete(new LambdaQueryWrapper<PStoreProductAttrValue>().eq(PStoreProductAttrValue::getProductId, productId));
        // 填充规格属性
        String attrStr = attr.stream().map(AttrBo::getName).collect(Collectors.joining(","));
        attrValues.forEach(e -> {
            e.setAttrValue(attrStr);
            e.setProductId(add.getId());
        });
        attrValueMapper.insertBatch(attrValues);
        // 设置购物券
        List<Long> couponIds = bo.getCouponIds();
        if (CollectionUtil.isNotEmpty(couponIds)) {
            // 删除旧的购物券联系表
            couponMapper.delete(new LambdaQueryWrapper<PStoreProductCoupon>().eq(PStoreProductCoupon::getProductId, productId));
            // 重新设置
            List<PStoreProductCoupon> couponBos = new ArrayList<>();
            couponIds.forEach(e -> {
                PStoreProductCoupon productCouponBo = new PStoreProductCoupon();
                productCouponBo.setProductId(add.getId());
                productCouponBo.setIssueCouponId(e);
                couponBos.add(productCouponBo);
            });

            couponMapper.insertBatch(couponBos);
        }

        return true;
    }

    @Override
    public TableDataInfo<PStoreProduct> hostList(PageQuery pageQuery) {
        Page<PStoreProduct> list = this.baseMapper.selectListCustom(pageQuery.build(), new LambdaQueryWrapper<PStoreProduct>()
            .eq(PStoreProduct::getDelFlag, "0")
            .eq(PStoreProduct::getIsHot, "1"));
        return TableDataInfo.build(list);
    }

    @Override
    public TableDataInfo<PStoreProduct> bestList(PageQuery pageQuery) {
        Page<PStoreProduct> list = this.baseMapper.selectListCustom(pageQuery.build(), new LambdaQueryWrapper<PStoreProduct>()
            .eq(PStoreProduct::getDelFlag, "0")
            .eq(PStoreProduct::getIsBest, "1"));
        return TableDataInfo.build(list);
    }

    @Override
    public TableDataInfo<PStoreSeckill> seckillList(PageQuery pageQuery) {
        Page<PStoreSeckill> list = this.pStoreSeckillMapper.selectListCustom(pageQuery.build(), new LambdaQueryWrapper<PStoreSeckill>().eq(PStoreSeckill::getIsDel, 0)
            .eq(PStoreSeckill::getStatus, 1));
        return TableDataInfo.build(list);
    }

    @Override
    public TableDataInfo<PStoreProduct> listByCateId(String cateId, PageQuery pageQuery) {
        Page<PStoreProduct> list = this.baseMapper.selectListCustom(pageQuery.build(), new LambdaQueryWrapper<PStoreProduct>().eq(PStoreProduct::getCateId, cateId));
        return TableDataInfo.build(list);
    }

    @Override
    public TableDataInfo<PStoreProduct> integralProductList(PageQuery pageQuery) {
        pageQuery.setPageNum((pageQuery.getPageNum() - 1) * pageQuery.getPageSize());
        return TableDataInfo.build(this.baseMapper.integralProductList(pageQuery));
    }
}
